package com.core.cloudcommon.security;

import com.core.cloudcommon.CommonCustomException;

import java.util.regex.Pattern;

/**
 * @author =====Lqj=====
 * @className PasswordValidator
 * @description 密码强度验证工具类
 * @create 2024/12/16 10:00
 **/
public class PasswordValidator {

    // 密码强度正则：至少8位，包含大小写字母、数字、特殊字符
    private static final String STRONG_PASSWORD_REGEX = 
        "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,20}$";
    
    // 中等强度密码：至少6位，包含字母和数字
    private static final String MEDIUM_PASSWORD_REGEX = 
        "^(?=.*[a-zA-Z])(?=.*\\d)[A-Za-z\\d@$!%*?&]{6,20}$";

    private static final Pattern STRONG_PATTERN = Pattern.compile(STRONG_PASSWORD_REGEX);
    private static final Pattern MEDIUM_PATTERN = Pattern.compile(MEDIUM_PASSWORD_REGEX);

    /**
     * 验证密码是否为强密码
     * @param password 密码
     * @return true-强密码，false-非强密码
     */
    public static boolean isStrongPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            return false;
        }
        return STRONG_PATTERN.matcher(password).matches();
    }

    /**
     * 验证密码是否为中等强度密码
     * @param password 密码
     * @return true-中等强度，false-弱密码
     */
    public static boolean isMediumPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            return false;
        }
        return MEDIUM_PATTERN.matcher(password).matches();
    }

    /**
     * 验证密码强度（抛出异常）
     * @param password 密码
     * @throws CommonCustomException 密码强度不够时抛出异常
     */
    public static void validatePasswordStrength(String password) {
        if (password == null || password.trim().isEmpty()) {
            throw new CommonCustomException(200012, "密码不能为空");
        }

        if (password.length() < 6) {
            throw new CommonCustomException(200013, "密码长度不能少于6位");
        }

        if (password.length() > 20) {
            throw new CommonCustomException(200014, "密码长度不能超过20位");
        }

        if (!isMediumPassword(password)) {
            throw new CommonCustomException(200015, 
                "密码强度不够：至少6位，必须包含字母和数字");
        }
    }

    /**
     * 验证强密码（抛出异常）
     * @param password 密码
     * @throws CommonCustomException 密码强度不够时抛出异常
     */
    public static void validateStrongPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            throw new CommonCustomException(200012, "密码不能为空");
        }

        if (!isStrongPassword(password)) {
            throw new CommonCustomException(200016, 
                "密码强度不够：至少8位，必须包含大小写字母、数字和特殊字符(@$!%*?&)");
        }
    }

    /**
     * 获取密码强度等级
     * @param password 密码
     * @return 1-弱密码，2-中等密码，3-强密码
     */
    public static int getPasswordStrength(String password) {
        if (password == null || password.trim().isEmpty()) {
            return 0;
        }

        if (isStrongPassword(password)) {
            return 3;
        } else if (isMediumPassword(password)) {
            return 2;
        } else {
            return 1;
        }
    }

    /**
     * 检查密码是否包含常见弱密码
     * @param password 密码
     * @return true-是弱密码，false-不是弱密码
     */
    public static boolean isWeakPassword(String password) {
        if (password == null) {
            return true;
        }

        String lowerPassword = password.toLowerCase();
        
        // 常见弱密码列表
        String[] weakPasswords = {
            "123456", "password", "123456789", "12345678", "12345",
            "1234567", "admin", "123123", "qwerty", "abc123",
            "password123", "admin123", "root", "guest", "test"
        };

        for (String weak : weakPasswords) {
            if (lowerPassword.equals(weak)) {
                return true;
            }
        }

        // 检查是否为连续数字或字母
        if (isSequentialChars(password)) {
            return true;
        }

        // 检查是否为重复字符
        if (isRepeatedChars(password)) {
            return true;
        }

        return false;
    }

    /**
     * 检查是否为连续字符
     */
    private static boolean isSequentialChars(String password) {
        if (password.length() < 3) {
            return false;
        }

        for (int i = 0; i < password.length() - 2; i++) {
            char c1 = password.charAt(i);
            char c2 = password.charAt(i + 1);
            char c3 = password.charAt(i + 2);

            if (c2 == c1 + 1 && c3 == c2 + 1) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查是否为重复字符
     */
    private static boolean isRepeatedChars(String password) {
        if (password.length() < 3) {
            return false;
        }

        char firstChar = password.charAt(0);
        for (int i = 1; i < password.length(); i++) {
            if (password.charAt(i) != firstChar) {
                return false;
            }
        }
        return true;
    }

    /**
     * 完整的密码验证（包含弱密码检查）
     * @param password 密码
     * @throws CommonCustomException 密码不符合要求时抛出异常
     */
    public static void validatePassword(String password) {
        // 基础强度验证
        validatePasswordStrength(password);

        // 弱密码检查
        if (isWeakPassword(password)) {
            throw new CommonCustomException(200017, 
                "密码过于简单，请使用更复杂的密码");
        }
    }
}
